using System;
using CKS.EBE.API;
using Microsoft.SharePoint;
using System.Text.RegularExpressions;
using System.Diagnostics;
using CKS.EBE.Linkbacks;
using System.Text;

namespace CKS.EBE
{
	public class PostEventReceiver : SPItemEventReceiver
	{
		public override void ItemAdded(SPItemEventProperties properties)
		{
			ProcessItem(properties);
		}

		public override void ItemUpdated(SPItemEventProperties properties)
		{
			ProcessItem(properties);
		}

		public override void ItemDeleted(SPItemEventProperties properties)
		{
		}

		/// <summary>
		/// Update Title for URL, Update Categories and process linkbacks
		/// </summary>
		/// <param name="properties"></param>
		private void ProcessItem(SPItemEventProperties properties)
		{
			SPListItem postListItem = properties.ListItem;

			DisableEventFiring();

			UpdateTitleForUrl(postListItem);
			UpdateCategories(postListItem);

			ProcessLinkbacks(properties.OpenWeb(), postListItem);

			EnableEventFiring();
		}

		private static void ProcessLinkbacks(SPWeb web, SPListItem item)
		{
			try
			{
				var linkbackPinger = new LinkbackPinger(web);
				linkbackPinger.SendLinkbackPings(item);
			}
			catch (Exception ex)
			{
				Trace.Write(ex);
			}
		}

		private static void UpdateCategories(SPListItem item)
		{
			try
			{
				Trace.Write("Updating categories");
				string categoriesFieldName = Localization.GetFieldName(Localization.FieldNames.Categories, item.Web.Language);
				var categories = (SPFieldLookupValueCollection)item[categoriesFieldName];

				if (categories.Count == 0 && item.ParentList.Fields.ContainsField("MultiCategory"))
				{
					Trace.Write("Adding categories");
					try
					{
						var multiCategories = (SPFieldLookupValueCollection)item["MultiCategory"];
						if (multiCategories.Count > 0)
						{
							item[categoriesFieldName] = multiCategories;
							categories = multiCategories;

							item.SystemUpdate();
						}
					}
					catch { }
				}

				var categoriesAsString = new StringBuilder();
				foreach (SPFieldLookupValue category in categories)
				{
					categoriesAsString.AppendFormat("{0};", category.LookupValue);
				}

				Trace.Write("Categories: " + categoriesAsString);
				item["CategoriesAsText"] = categoriesAsString.ToString().TrimEnd(new[] { '~' });
				item.SystemUpdate();
			}
			catch (Exception ex)
			{
				Trace.Write(ex);
			}
		}

		public static void UpdateTitleForUrl(SPListItem item)
		{
			try
			{
				if (string.IsNullOrEmpty((string)item["BlogTitleForUrl"]))
				{
					string sNewTitle = CleanString(item.Title);
					API.IUrlProvider urlProvider = new DefaultUrlProvider();

					SPListItem oExisting = urlProvider.GetPostFromUrlTitle(sNewTitle, item.Web);
					int count = 1;
					while (oExisting != null && count < 100)
					{
						oExisting = urlProvider.GetPostFromUrlTitle(sNewTitle + "-" + count, item.Web);
						if (oExisting == null) sNewTitle += "-" + count;
						count++;
					}

					item["BlogTitleForUrl"] = sNewTitle;
					item.SystemUpdate();
				}
			}
			catch (Exception ex)
			{
				Trace.Write("Failed to update URL title");
				Trace.Write(ex);
				throw;
			}
		}

		private static string CleanString(string sInput)
		{
			string output = sInput;

			// get rid of URI escapes
			output = Regex.Replace(output, "%[a-fA-F0-9]{2}", "", RegexOptions.Compiled);
			// get rid of HTML escapes
			output = Regex.Replace(output, @"&(\#{1}\d*|\w*);", "", RegexOptions.Compiled);
			// Handle <
			output = Regex.Replace(output, @"<", " lt ", RegexOptions.Compiled);
			// Handle >
			output = Regex.Replace(output, @">", " gt ", RegexOptions.Compiled);
			// Handle Quotes
			output = Regex.Replace(output, @"""", " quote ", RegexOptions.Compiled);
			// Handle .
			output = Regex.Replace(output, @"\.", "-", RegexOptions.Compiled);
			// go to town on special characters
			output = Regex.Replace(output, @"[~`!@#$%^*()<>?,./:;'""\\]", "", RegexOptions.Compiled);
			// replace ampersands with the word 'and', providing they're surrounded by white space
			output = Regex.Replace(output, @"\s&\s", @" amp ", RegexOptions.Compiled);
			// replace all other ampersands with hyphens
			output = output.Replace("&", "-");
			// get rid of groups of spaces (ie 2 or more in a row)
			output = Regex.Replace(output, @"\s{2,}", " ", RegexOptions.Compiled);
			// replace spaces with dashes
			output = output.Trim();
			output = Regex.Replace(output, @"\s", "-", RegexOptions.Compiled);
			output = Regex.Replace(output, @"-{2,}", "-", RegexOptions.Compiled);

			for (int charpos = output.Length - 1; charpos > -1; charpos--)
			{
				char c = output[charpos];
				if (c != 45 && !(c >= 48 && c <= 57) && !(c >= 65 && c <= 90) && c != 95 && !(c >= 97 && c <= 122))
				{
					output.Remove(charpos);
				}
			}

			return output.ToLower();
		}
	}
}